// 智能设备控制中心 - Arduino端代码
// 支持8路继电器控制、温湿度监测、电流检测和LCD显示

#include <ArduinoJson.h>
#include <DHT.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>

// 引脚定义
#define RELAY_1 2
#define RELAY_2 3
#define RELAY_3 4
#define RELAY_4 5
#define RELAY_5 6
#define RELAY_6 7
#define RELAY_7 8
#define RELAY_8 9
#define DHTPIN_1 A0
#define DHTPIN_2 A1
#define CURRENT_PIN_1 A2
#define CURRENT_PIN_2 A3
#define CURRENT_PIN_3 A4
#define CURRENT_PIN_4 A5
#define BEEP_PIN 10
#define BUTTON1 11
#define BUTTON2 12
#define BUTTON3 13

// DHT传感器类型
#define DHTTYPE DHT22

// LCD引脚定义
LiquidCrystal lcd(14, 15, 16, 17, 18, 19);

// 创建DHT对象
DHT dht1(DHTPIN_1, DHTTYPE);
DHT dht2(DHTPIN_2, DHTTYPE);

// 系统状态变量
bool relayStates[8] = {false, false, false, false, false, false, false, false};
float temperatures[2] = {0.0, 0.0};
float humidities[2] = {0.0, 0.0};
float currents[4] = {0.0, 0.0, 0.0, 0.0};
unsigned long lastSensorUpdate = 0;
const unsigned long sensorUpdateInterval = 5000; // 5秒更新一次传感器

// EEPROM地址定义
#define RELAY_STATE_ADDR 0

void setup() {
  // 初始化串口通信
  Serial.begin(9600);
  
  // 初始化LCD显示屏
  lcd.begin(16, 2);
  lcd.print("智能控制中心");
  lcd.setCursor(0, 1);
  lcd.print("启动中...");
  
  // 初始化DHT传感器
  dht1.begin();
  dht2.begin();
  
  // 设置继电器引脚为输出模式
  pinMode(RELAY_1, OUTPUT);
  pinMode(RELAY_2, OUTPUT);
  pinMode(RELAY_3, OUTPUT);
  pinMode(RELAY_4, OUTPUT);
  pinMode(RELAY_5, OUTPUT);
  pinMode(RELAY_6, OUTPUT);
  pinMode(RELAY_7, OUTPUT);
  pinMode(RELAY_8, OUTPUT);
  
  // 设置蜂鸣器引脚为输出模式
  pinMode(BEEP_PIN, OUTPUT);
  
  // 设置按钮引脚为输入模式
  pinMode(BUTTON1, INPUT_PULLUP);
  pinMode(BUTTON2, INPUT_PULLUP);
  pinMode(BUTTON3, INPUT_PULLUP);
  
  // 从EEPROM加载继电器状态
  loadRelayStates();
  
  // 更新继电器状态
  updateRelayStates();
  
  // 初始化完成提示音
  beep(200);
  
  // 更新LCD显示
  updateLcdDisplay();
}

void loop() {
  // 定期更新传感器数据
  unsigned long currentMillis = millis();
  if (currentMillis - lastSensorUpdate >= sensorUpdateInterval) {
    lastSensorUpdate = currentMillis;
    
    // 读取温湿度数据
    readSensorData();
    
    // 读取电流数据
    readCurrentData();
    
    // 发送系统状态数据到服务器
    sendSystemStatus();
    
    // 更新LCD显示
    updateLcdDisplay();
  }
  
  // 检查按钮状态
  checkButtons();
  
  // 检查串口命令
  checkSerialCommands();
  
  // 小延迟
  delay(100);
}

// 蜂鸣器发声函数
void beep(int duration) {
  digitalWrite(BEEP_PIN, HIGH);
  delay(duration);
  digitalWrite(BEEP_PIN, LOW);
}

// 读取传感器数据
void readSensorData() {
  // 读取第一个DHT传感器数据
  temperatures[0] = dht1.readTemperature();
  humidities[0] = dht1.readHumidity();
  
  // 检查数据是否有效
  if (isnan(temperatures[0]) || isnan(humidities[0])) {
    temperatures[0] = 0.0;
    humidities[0] = 0.0;
  }
  
  // 读取第二个DHT传感器数据
  temperatures[1] = dht2.readTemperature();
  humidities[1] = dht2.readHumidity();
  
  // 检查数据是否有效
  if (isnan(temperatures[1]) || isnan(humidities[1])) {
    temperatures[1] = 0.0;
    humidities[1] = 0.0;
  }
}

// 读取电流传感器数据
void readCurrentData() {
  // 读取四个电流传感器数据
  for (int i = 0; i < 4; i++) {
    int sensorValue = analogRead(A2 + i);
    // 将模拟值转换为电流值 (假设使用ACS712 5A传感器)
    // 5V参考电压，1023为满量程，灵敏度为185mV/A
    float voltage = sensorValue * (5.0 / 1023.0);
    float current = (voltage - 2.5) / 0.185; // 2.5V为零点
    
    // 确保电流值为非负数
    if (current < 0) current = 0;
    
    currents[i] = current;
  }
}

// 更新继电器状态
void updateRelayStates() {
  digitalWrite(RELAY_1, relayStates[0] ? HIGH : LOW);
  digitalWrite(RELAY_2, relayStates[1] ? HIGH : LOW);
  digitalWrite(RELAY_3, relayStates[2] ? HIGH : LOW);
  digitalWrite(RELAY_4, relayStates[3] ? HIGH : LOW);
  digitalWrite(RELAY_5, relayStates[4] ? HIGH : LOW);
  digitalWrite(RELAY_6, relayStates[5] ? HIGH : LOW);
  digitalWrite(RELAY_7, relayStates[6] ? HIGH : LOW);
  digitalWrite(RELAY_8, relayStates[7] ? HIGH : LOW);
  
  // 保存继电器状态到EEPROM
  saveRelayStates();
  
  // 蜂鸣提示
  beep(100);
}

// 保存继电器状态到EEPROM
void saveRelayStates() {
  for (int i = 0; i < 8; i++) {
    EEPROM.write(RELAY_STATE_ADDR + i, relayStates[i]);
  }
  EEPROM.commit(); // 对于支持commit的板子
}

// 从EEPROM加载继电器状态
void loadRelayStates() {
  for (int i = 0; i < 8; i++) {
    relayStates[i] = EEPROM.read(RELAY_STATE_ADDR + i);
  }
}

// 发送系统状态数据
void sendSystemStatus() {
  // 创建JSON对象
  StaticJsonDocument<256> doc;
  
  // 添加继电器状态
  JsonArray relays = doc.createNestedArray("relays");
  for (int i = 0; i < 8; i++) {
    relays.add(relayStates[i]);
  }
  
  // 添加温度数据
  JsonArray temps = doc.createNestedArray("temperatures");
  for (int i = 0; i < 2; i++) {
    temps.add(temperatures[i]);
  }
  
  // 添加湿度数据
  JsonArray hums = doc.createNestedArray("humidities");
  for (int i = 0; i < 2; i++) {
    hums.add(humidities[i]);
  }
  
  // 添加电流数据
  JsonArray curs = doc.createNestedArray("currents");
  for (int i = 0; i < 4; i++) {
    curs.add(currents[i]);
  }
  
  // 发送JSON数据
  serializeJson(doc, Serial);
  Serial.println();
}

// 处理串口命令
void checkSerialCommands() {
  if (Serial.available() > 0) {
    String command = Serial.readStringUntil('\n');
    command.trim();
    
    // 处理继电器控制命令
    if (command.startsWith("RELAY")) {
      int relayIndex = command.substring(5).toInt() - 1;
      if (relayIndex >= 0 && relayIndex < 8) {
        if (command.indexOf("ON") > 0) {
          relayStates[relayIndex] = true;
        } else if (command.indexOf("OFF") > 0) {
          relayStates[relayIndex] = false;
        }
        updateRelayStates();
        
        // 回复命令确认
        Serial.print("OK: ");
        Serial.println(command);
      }
    }
    // 处理蜂鸣器命令
    else if (command.startsWith("BEEP")) {
      int duration = command.substring(5).toInt();
      if (duration > 0) {
        beep(duration);
        Serial.println("OK: BEEP");
      }
    }
    // 处理状态查询命令
    else if (command.equals("STATUS")) {
      sendSystemStatus();
    }
    // 处理显示命令
    else if (command.startsWith("DISPLAY")) {
      String message = command.substring(7);
      updateLcdDisplay(message);
      Serial.println("OK: DISPLAY");
    }
    // 处理未知命令
    else {
      Serial.print("ERROR: Unknown command: ");
      Serial.println(command);
    }
  }
}

// 检查按钮状态
void checkButtons() {
  // 按钮1：设备全开关
  if (digitalRead(BUTTON1) == LOW) {
    bool allOn = true;
    for (int i = 0; i < 8; i++) {
      if (!relayStates[i]) {
        allOn = false;
        break;
      }
    }
    
    // 全开关逻辑：如果所有设备都开启，则关闭所有设备；否则开启所有设备
    bool newState = !allOn;
    for (int i = 0; i < 8; i++) {
      relayStates[i] = newState;
    }
    
    updateRelayStates();
    
    // 按钮防抖
    delay(300);
  }
  
  // 按钮2：场景1（回家模式）
  if (digitalRead(BUTTON2) == LOW) {
    // 回家模式：打开主灯和空调
    relayStates[0] = true; // 主灯
    relayStates[1] = true; // 空调
    
    updateRelayStates();
    
    // 按钮防抖
    delay(300);
  }
  
  // 按钮3：场景2（睡眠模式）
  if (digitalRead(BUTTON3) == LOW) {
    // 睡眠模式：关闭主灯，打开风扇和加湿器
    relayStates[0] = false; // 关闭主灯
    relayStates[2] = true;  // 打开风扇
    relayStates[4] = true;  // 打开加湿器
    
    updateRelayStates();
    
    // 按钮防抖
    delay(300);
  }
}

// 更新LCD显示
void updateLcdDisplay() {
  lcd.clear();
  
  // 第一行显示温度和湿度
  lcd.setCursor(0, 0);
  lcd.print("T:");
  lcd.print(temperatures[0]);
  lcd.print("C H:");
  lcd.print(humidities[0]);
  lcd.print("%");
  
  // 第二行显示设备状态
  lcd.setCursor(0, 1);
  lcd.print("设备:");
  int onCount = 0;
  for (int i = 0; i < 8; i++) {
    if (relayStates[i]) onCount++;
  }
  lcd.print(onCount);
  lcd.print("/8");
}

// 自定义LCD显示内容
void updateLcdDisplay(String message) {
  lcd.clear();
  
  // 显示消息
  if (message.length() <= 16) {
    lcd.setCursor(0, 0);
    lcd.print(message);
  } else {
    lcd.setCursor(0, 0);
    lcd.print(message.substring(0, 16));
    lcd.setCursor(0, 1);
    lcd.print(message.substring(16));
  }
}